---
title: "Writing Data"
sidebar_position: 4
description: "Insert, update, and delete data in Convex database tables"
---

import insertExample from "!!raw-loader!@site/../private-demos/snippets/convex/writingDataInsert.ts";
import patchExample from "!!raw-loader!@site/../private-demos/snippets/convex/writingDataPatch.ts";
import replaceExample from "!!raw-loader!@site/../private-demos/snippets/convex/writingDataReplace.ts";
import deleteExample from "!!raw-loader!@site/../private-demos/snippets/convex/writingDataDelete.ts";
import { ComponentCardList } from "@site/src/components/ComponentCard";

[Mutations](/functions/mutation-functions.mdx) can insert, update, and remove
data from database tables.

## Inserting new documents

You can create new documents in the database with the
[`db.insert`](/api/interfaces/server.GenericDatabaseWriter#insert) method:

<TSAndJSSnippet
  title="convex/tasks.ts"
  sourceTS={insertExample}
  sourceJS={insertExample}
  highlightPatterns={["db.insert"]}
/>

The second argument to `db.insert` is a JavaScript object with data for the new
document.

The same types of values that can be passed into and returned from
[queries](/functions/query-functions.mdx) and
[mutations](/functions/mutation-functions.mdx) can be written into the database.
See [Data Types](/database/types.md) for the full list of supported types.

The `insert` method returns a globally unique ID for the newly inserted
document.

## Updating existing documents

Given an existing document ID the document can be updated using the following
methods:

1. The [`db.patch`](/api/interfaces/server.GenericDatabaseWriter#patch) method
   will patch an existing document, shallow merging it with the given partial
   document. New fields are added. Existing fields are overwritten. Fields set
   to `undefined` are removed.

<TSAndJSSnippet
  title="convex/tasks.ts"
  sourceTS={patchExample}
  sourceJS={patchExample}
  highlightPatterns={["db.patch"]}
/>

2. The [`db.replace`](/api/interfaces/server.GenericDatabaseWriter#replace)
   method will replace the existing document entirely, potentially removing
   existing fields:

<TSAndJSSnippet
  title="convex/tasks.ts"
  sourceTS={replaceExample}
  sourceJS={replaceExample}
  highlightPatterns={["db.replace"]}
/>

## Deleting documents

Given an existing document ID the document can be removed from the table with
the [`db.delete`](/api/interfaces/server.GenericDatabaseWriter#delete) method.

<TSAndJSSnippet
  title="convex/tasks.ts"
  sourceTS={deleteExample}
  sourceJS={deleteExample}
  highlightPatterns={["db.delete"]}
/>

## Bulk inserts or updates

If you are used to SQL you might be looking for some sort of bulk insert or bulk
update statement. In Convex the entire `mutation` function is automatically a
single transaction.

You can just insert or update in a loop in the mutation function. Convex queues
up all database changes in the function and executes them all in a single
transaction when the function ends, leading to a single efficient change to the
database.

````typescript
/**
 * Bulk insert multiple products into the database.
 *
 * Equivalent to the SQL:
 * ```sql
 * INSERT INTO products (product_id, product_name, category, price, in_stock)
 * VALUES
 *     ('Laptop Pro', 'Electronics', 1299.99, true),
 *     ('Wireless Mouse', 'Electronics', 24.95, true),
 *     ('Ergonomic Keyboard', 'Electronics', 89.50, true),
 *     ('Ultra HD Monitor', 'Electronics', 349.99, false),
 *     ('Wireless Headphones', 'Audio', 179.99, true);
 * ```
 */
export const bulkInsertProducts = mutation({
  args: {
    products: v.array(
      v.object({
        product_name: v.string(),
        category: v.string(),
        price: v.number(),
        in_stock: v.boolean(),
      }),
    ),
  },
  handler: async (ctx, args) => {
    const { products } = args;

    // Insert in a loop. This is efficient because Convex queues all the changes
    // to be executed in a single transaction when the mutation ends.
    for (const product of products) {
      const id = await ctx.db.insert("products", {
        product_name: product.product_name,
        category: product.category,
        price: product.price,
        in_stock: product.in_stock,
      });
    }
  },
});
````

## Migrations

Database migrations are done through the migration component. The component is
designed to run online migrations to safely evolve your database schema over
time. It allows you to resume from failures, and validate changes with dry runs.

<ComponentCardList
  items={[
    {
      title: "Migrations",
      description: "Framework for long running data migrations of live data.",
      href: "https://www.convex.dev/components/migrations",
    },
  ]}
/>

## Write performance and limits

To prevent accidental writes of large amounts of records, queries and mutations
enforce limits detailed [here](/production/state/limits.mdx#transactions).
